import 'dart:async';
import 'dart:io';
import 'package:casdon/common/widget/common_loading_widget.dart';
import 'package:casdon/common/widget/conform_dialog.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:video_player/video_player.dart';
import 'package:chewie/chewie.dart';

/// 支持三种资源类型
abstract class VideoSource {
  const VideoSource();

  factory VideoSource.network(String url) = NetworkSource;
  factory VideoSource.file(File file) = FileSource;
  factory VideoSource.asset(String path) = AssetSource;

  VideoPlayerController createController();
}

class NetworkSource extends VideoSource {
  final String url;
  const NetworkSource(this.url);
  @override
  VideoPlayerController createController() =>
      VideoPlayerController.networkUrl(Uri.parse(url));
}

class FileSource extends VideoSource {
  final File file;
  const FileSource(this.file);
  @override
  VideoPlayerController createController() => VideoPlayerController.file(file);
}

class AssetSource extends VideoSource {
  final String path;
  const AssetSource(this.path);
  @override
  VideoPlayerController createController() => VideoPlayerController.asset(path);
}

/// 封装的播放器组件
class VideoPlayerWidget extends StatefulWidget {
  final VideoSource source;

  const VideoPlayerWidget({super.key, required this.source});

  @override
  State<VideoPlayerWidget> createState() => _VideoPlayerWidgetState();
}

class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
  VideoPlayerController? _videoController;
  ChewieController? _chewieController;
  StreamSubscription<List<ConnectivityResult>>? _connectivitySub;
  bool _isOffline = false;
  bool _wasPlayingBeforeOffline = false;
  bool _isInitializing = false;
  bool _requiresCellularConsent = false;
  bool _cellularConfirmed = false;
  bool _isPromptingCellular = false;

  @override
  void initState() {
    super.initState();
    _listenConnectivity();
    _initPlayer();
  }

  @override
  void dispose() {
    _connectivitySub?.cancel();
    _videoController?.dispose();
    _chewieController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final chewie = _chewieController;
    final controller = _videoController;
    if (chewie == null ||
        controller == null ||
        !controller.value.isInitialized) {
      return const Center(child: CommonLoadingWidget());
    }
    final videoSize = controller.value.size;
    final aspect = videoSize.width == 0
        ? 16 / 9
        : videoSize.width / videoSize.height;

    return Center(
      child: AspectRatio(
        aspectRatio: aspect,
        child: Chewie(controller: chewie),
      ),
    );
  }

  Future<void> _initPlayer({bool autoPlay = true}) async {
    if (_isInitializing) return;
    _isInitializing = true;
    final prevController = _videoController;
    final prevChewie = _chewieController;

    final controller = widget.source.createController();
    ChewieController? chewie;
    try {
      await controller.initialize();
      if (!mounted) {
        controller.dispose();
        return;
      }
      chewie = ChewieController(
        videoPlayerController: controller,
        autoInitialize: false,
        autoPlay: autoPlay && (!_requiresCellularConsent || _cellularConfirmed),
        showControls: true,
        looping: false,
        aspectRatio: controller.value.aspectRatio == 0
            ? 16 / 9
            : controller.value.aspectRatio,
        customControls: _CustomControls(onPlayRequest: _handlePlayRequest),
        allowFullScreen: true,
        placeholder: Container(
          color: Colors.black,
          alignment: Alignment.center,
          child: const CommonLoadingWidget(),
        ),
        progressIndicatorDelay: const Duration(milliseconds: 200),
      );

      setState(() {
        _videoController = controller;
        _chewieController = chewie;
      });

      prevController?.dispose();
      prevChewie?.dispose();
    } catch (e) {
      debugPrint('Video init error: $e');
      controller.dispose();
      chewie?.dispose();
    } finally {
      _isInitializing = false;
    }
  }

  void _listenConnectivity() {
    _connectivitySub = Connectivity().onConnectivityChanged.listen(
      _handleConnectivityChange,
    );
    Connectivity().checkConnectivity().then(_handleConnectivityChange);
  }

  Future<void> _handleConnectivityChange(dynamic results) async {
    final list = results is List<ConnectivityResult>
        ? results
        : <ConnectivityResult>[if (results is ConnectivityResult) results];
    final offline =
        list.isEmpty || list.every((r) => r == ConnectivityResult.none);
    if (offline) {
      if (!_isOffline) {
        _pauseForOffline();
        if (mounted) {
          setState(() => _isOffline = true);
        }
      }
      return;
    }

    if (_isOffline) {
      if (mounted) {
        setState(() {
          _isOffline = false;
        });
      } else {
        _isOffline = false;
      }
      await _resumeAfterReconnect();
    }

    final onCellular = list.any((r) => r == ConnectivityResult.mobile);
    _requiresCellularConsent = onCellular && !_cellularConfirmed;
    if (_requiresCellularConsent && !_cellularConfirmed) {
      _pauseForOffline();
      await _maybePromptCellular();
    }
  }

  void _pauseForOffline() {
    final controller = _videoController;
    if (controller == null) return;
    _wasPlayingBeforeOffline = controller.value.isPlaying;
    controller.pause();
  }

  Future<void> _resumeAfterReconnect() async {
    final controller = _videoController;
    if (controller == null || !controller.value.isInitialized) {
      await _initPlayer(autoPlay: _wasPlayingBeforeOffline);
      return;
    }
    if (_wasPlayingBeforeOffline) {
      await controller.play();
    }
  }

  Future<void> _maybePromptCellular() async {
    if (_isPromptingCellular ||
        _cellularConfirmed ||
        !_requiresCellularConsent) {
      return;
    }
    _isPromptingCellular = true;
    final ret = await showCustomConfirmDialog(
      context: context,
      title: '流量播放提示',
      content: '当前使用移动网络，播放视频可能产生流量费用，是否继续播放？',
      cancelText: '取消',
      confirmText: '继续播放',
    );
    if (ret == true) {
      _cellularConfirmed = true;
      _requiresCellularConsent = false;
      // 恢复播放
      final controller = _videoController;
      if (controller != null && controller.value.isInitialized) {
        await controller.play();
      }
    }
    _isPromptingCellular = false;
  }

  Future<bool> _handlePlayRequest() async {
    if (!_requiresCellularConsent || _cellularConfirmed) {
      return true;
    }
    await _maybePromptCellular();
    return _cellularConfirmed;
  }
}

class _CustomControls extends StatefulWidget {
  const _CustomControls({this.onPlayRequest});

  final Future<bool> Function()? onPlayRequest;

  @override
  State<_CustomControls> createState() => _CustomControlsState();
}

class _CustomControlsState extends State<_CustomControls> {
  VideoPlayerController? _controller;
  ChewieController? _chewieController;

  void _seekRelative(VideoPlayerController controller, int seconds) {
    final current = controller.value.position;
    final target = current + Duration(seconds: seconds);
    final duration = controller.value.duration;
    final boundedStart = target < Duration.zero ? Duration.zero : target;
    final clamped = duration > Duration.zero && boundedStart > duration
        ? duration
        : boundedStart;
    controller.seekTo(clamped);
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted) return;
      _chewieController = ChewieController.of(context);
      _controller = _chewieController?.videoPlayerController;
      _controller?.addListener(_onControllerUpdate);
    });
  }

  @override
  void dispose() {
    _controller?.removeListener(_onControllerUpdate);
    super.dispose();
  }

  void _onControllerUpdate() {
    if (mounted) {
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    final chewieController = _chewieController ?? ChewieController.of(context);
    final videoController = chewieController.videoPlayerController;
    final isPlaying = videoController.value.isPlaying;
    final isCompleted =
        videoController.value.position >= videoController.value.duration;

    return Align(
      alignment: Alignment.bottomCenter,
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            VideoProgressIndicator(videoController, allowScrubbing: true),

            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                _controlButton(
                  icon: Icons.replay_10,
                  onPressed: () => _seekRelative(videoController, -15),
                ),
                SizedBox(width: 1.w),
                _controlButton(
                  icon: (isPlaying && !isCompleted)
                      ? Icons.pause
                      : Icons.play_arrow,
                  onPressed: () async {
                    if (widget.onPlayRequest != null) {
                      final allow = await widget.onPlayRequest!.call();
                      if (!allow) return;
                    }
                    setState(() {
                      if (isPlaying) {
                        videoController.pause();
                      } else {
                        if (isCompleted) {
                          videoController.seekTo(Duration.zero);
                        }
                        videoController.play();
                      }
                    });
                  },
                ),
                SizedBox(width: 12.w),
                _controlButton(
                  icon: Icons.forward_10,
                  onPressed: () => _seekRelative(videoController, 15),
                ),
                SizedBox(width: 12.w),
                SizedBox(
                  width: 48.w,
                  height: 48.w,
                  child: PopupMenuButton<double>(
                    padding: EdgeInsets.zero,
                    offset: const Offset(0, -6),
                    icon: Icon(Icons.speed, color: Colors.white, size: 36.w),
                    onSelected: (speed) =>
                        videoController.setPlaybackSpeed(speed),
                    itemBuilder: (_) => [0.5, 1.0, 1.5, 2.0]
                        .map(
                          (s) => PopupMenuItem(value: s, child: Text('${s}x')),
                        )
                        .toList(),
                  ),
                ),
                SizedBox(width: 12.w),
                _controlButton(
                  icon: Icons.fullscreen,
                  onPressed: () => chewieController.enterFullScreen(),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _controlButton({
    required IconData icon,
    required VoidCallback onPressed,
  }) {
    return SizedBox(
      width: 48.w,
      height: 48.w,
      child: IconButton(
        onPressed: onPressed,
        padding: EdgeInsets.zero,
        iconSize: 36.w,
        color: Colors.white,
        constraints: BoxConstraints.tight(Size(36.w, 36.w)),
        icon: Icon(icon, size: 36.w),
      ),
    );
  }
}
